#include <stdio.h>
#include <stdbool.h>

#include "los_task.h"
#include "ohos_init.h"
#include "cmsis_os.h"
#include "config_network.h"
#include "iot_pwm.h"
#include "cJSON.h"

#include "device_mgr.h"
#include "iot.h"
#include "tcp.h"
#include "lcd.h"

// #define ROUTE_SSID "EU2025" // WiFi账号
// #define ROUTE_PASSWORD "88888888" // WiFi密码
#define ROUTE_SSID "Redmi_EFDA_02" // WiFi账号
#define ROUTE_PASSWORD "Aa@123456" // WiFi密码
// #define ROUTE_SSID "OHO_WIFI" // WiFi账号
// #define ROUTE_PASSWORD "12345678" // WiFi密码
// #define ROUTE_SSID "YLU2025" // WiFi账号
// #define ROUTE_PASSWORD "12345678" // WiFi密码
// #define ROUTE_SSID "C314" // WiFi账号
// #define ROUTE_PASSWORD "qwer1234" // WiFi密码
#define MSG_QUEUE_LENGTH 16
#define BUFFER_LEN 50

#define BEEP_PORT EPWMDEV_PWM5_M0

bool human_state = false;
bool light_state = false;
bool auto_state = false;

static unsigned int m_msg_queue;

void iot_thread(void *args)
{
    uint8_t mac_address[6] = {0x00, 0xdc, 0xb6, 0x90, 0x01, 0x00};

    FlashInit();
    VendorSet(VENDOR_ID_WIFI_MODE, "STA", 3); // 配置为Wifi STA模式
    VendorSet(VENDOR_ID_MAC, mac_address, 6); // 多人同时做该实验，请修改各自不同的WiFi MAC地址
    VendorSet(VENDOR_ID_WIFI_ROUTE_SSID, ROUTE_SSID, sizeof(ROUTE_SSID));
    VendorSet(VENDOR_ID_WIFI_ROUTE_PASSWD, ROUTE_PASSWORD, sizeof(ROUTE_PASSWORD));

reconnect:
    SetWifiModeOff();
    SetWifiModeOn();

    // mqtt_init();

    // while (1)
    // {
    //     if (!wait_message())
    //     {
    //         goto reconnect;
    //     }
    //     LOS_Msleep(1);
    // }
}

void device_ctl_thread(void *arg)
{
    double *data_ptr = NULL;

    // 新增：灯光阈值
    e_iot_data iot_data = {0};

    lcd_dev_init();
    lcd_load_ui();

    light_dev_init();
    door_init();

    iss_mq2_dev_s mq2_init;
    // mq2_dev_init(&mq2_init);
    gpio_dev_init();

    IoTPwmInit(BEEP_PORT);

    while (1)
    {
        LOS_QueueRead(m_msg_queue, (void *)&data_ptr, BUFFER_LEN, LOS_WAIT_FOREVER);

        if (!auto_state)
        {
            door_actuator_control();
            light_control();
        }

        LOS_Msleep(3000);
    }
}

int create_message(float data[], int data_len)
{
    if (data == NULL || data_len <= 0)
    {
        return -1;
    }

    memset(g_message_send, 0, sizeof(g_message_send));

    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        return -1;
    }

    cJSON_AddStringToObject(root, "root", "SMART_HOUSE");
    cJSON_AddStringToObject(root, "service_type", "data_upload");
    cJSON *msg_data_array = cJSON_AddArrayToObject(root, "message");

    cJSON *msg_data = cJSON_CreateObject();
    if (data == NULL)
    {
        cJSON_Delete(root);
        return -1;
    }

    char tmp_data[20] = {0};
    cJSON_AddStringToObject(msg_data, "position", "bedroom");
    sprintf(tmp_data, "%.2f", data[1]);
    cJSON_AddStringToObject(msg_data, "temperature", tmp_data);

    memset(tmp_data, 0, sizeof(tmp_data));
    sprintf(tmp_data, "%.2f", data[2]);
    cJSON_AddStringToObject(msg_data, "humidity", tmp_data);

    memset(tmp_data, 0, sizeof(tmp_data));
    sprintf(tmp_data, "%.2f", data[0]);
    cJSON_AddStringToObject(msg_data, "light_value", tmp_data);

    memset(tmp_data, 0, sizeof(tmp_data));
    sprintf(tmp_data, "%d", data[3]);
    cJSON_AddStringToObject(msg_data, "smoke", tmp_data);

    cJSON_AddStringToObject(msg_data, "garage_door", "ON");
    cJSON_AddItemToArray(msg_data_array, msg_data);

    char *json_string = cJSON_Print(root);
    if (json_string == NULL)
    {
        cJSON_Delete(root);
        return -1;
    }

    strncpy(g_message_send, json_string, sizeof(g_message_send) - 1);
    g_message_send[sizeof(g_message_send) - 1] = '\0';

    cJSON_Delete(root);
    free(json_string);

    return 0;
}
void device_read_thraed(void *arg)
{
    printf("device_read_thraed enter...\n");

    float read_data[5] = {0};

    i2c_dev_init();
    LOS_Msleep(1000);

    while (1)
    {
        get_light_value(&read_data[0]);

        get_tmp_hum_value(&read_data[1], &read_data[2]);

        float ppm = 0.0;
        int ret = get_mq2_ppm(&ppm);
        if (ret == 0)
        {
            read_data[3] = ppm;
            printf("MQ2 PPM: %.2f\n", read_data[3]);
        }

        LOS_QueueWrite(m_msg_queue, (void *)&read_data, sizeof(read_data), LOS_WAIT_FOREVER);

        if (create_message(read_data, 5) != 0)
        {
            printf("Failed to create message\n");
            continue;
        }

        LOS_Msleep(2000);
    }
}

void key_control(char *key_pressed)
{
    if (strcmp(key_pressed, "1234") == 0)
    {
        g_is_entry_door_open = true;
        // door_actuator_control();
    }
    else if (strcmp(key_pressed, "A1") == 0)
    {
        g_is_garage_door_open = !g_is_garage_door_open;\
        // door_actuator_control();
    }
    else if (strcmp(key_pressed, "A2") == 0)
    {
        g_is_window_open = !g_is_window_open;
        // door_actuator_control();
    }
    else if (strcmp(key_pressed, "D0") == 0)
    {
        g_is_light_on = !g_is_light_on;
        // light_control();
    }
    else
    {
        printf("Invalid keypad input: %s\n", key_pressed);
        lcd_show_string(0, 288, "Invalid input", LCD_RED, LCD_WHITE, 12, 0);
    }
}

void keypad_process(void *args)
{
    char key_vaule = 0;
    char key_pressed[17] = {0};
    while (1)
    {
        key_vaule = 0;
        int ret = get_key_pressed(&key_vaule);
        if (ret < 0)
        {
            printf("Failed to get key pressed\n");
            continue;
        }
        if (key_vaule == '*')
        {
            memset(key_pressed, 0, sizeof(key_pressed));
        }
        else if (key_vaule == '#')
        {
            key_control(key_pressed);
            memset(key_pressed, 0, sizeof(key_pressed));
        }
        else if (key_vaule != 0)
        {
            if (strlen(key_pressed) >= 16)
            {
                printf("Key pressed buffer is full, resetting...\n");
                memset(key_pressed, 0, sizeof(key_pressed));
            }
            strncat(key_pressed, &key_vaule, 1);
        }

        LOS_TaskDelay(200);
    }
    return;
}

void wifi_process(void *args)
{
    unsigned int threadID_client = 0, threadID_server = 0;
    unsigned int ret = LOS_OK;

    set_wifi_config_route_ssid(printf, ROUTE_SSID);       // 路由的WiFi名称
    set_wifi_config_route_passwd(printf, ROUTE_PASSWORD); // 路由器WiFi密码

    SetWifiModeOff();
    SetApModeOff();
    SetWifiModeOn();

    WifiLinkedInfo info;

    while (get_wifi_info(&info) != 0)
    {
        printf(".");
    }

    char server_info[32] = {0};
    sprintf(server_info, "IP:%d.%d.%d.%d   Port: %d", info.ipAddress & 0xFF, (info.ipAddress >> 8) & 0xFF, (info.ipAddress >> 16) & 0xFF,
            (info.ipAddress >> 24) & 0xFF, LISTEN_PORT);
    lcd_show_string(0, 288, server_info, LCD_RED, LCD_WHITE, 12, 0);

    CreateThread(&threadID_client, wifi_client, NULL, "client@ process");
    CreateThread(&threadID_server, wifi_server, NULL, "server@ process");
}

void smart_house_entry()
{
    unsigned int thread_id_1 = 0;
    unsigned int thread_id_2 = 0;
    unsigned int thread_id_3 = 0;
    unsigned int thread_id_4 = 0;
    TSK_INIT_PARAM_S task_1 = {0};
    TSK_INIT_PARAM_S task_2 = {0};
    TSK_INIT_PARAM_S task_3 = {0};
    TSK_INIT_PARAM_S task_4 = {0};
    unsigned int ret = LOS_OK;

    ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &m_msg_queue, 0, BUFFER_LEN);
    if (ret != LOS_OK)
    {
        printf("Falied to create Message Queue ret:0x%x\n", ret);
        return;
    }

    task_1.pfnTaskEntry = (TSK_ENTRY_FUNC)device_ctl_thread;
    task_1.uwStackSize = 2048;
    task_1.pcName = "device control thread";
    task_1.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_1, &task_1);
    if (ret != LOS_OK)
    {
        printf("Falied to create task ret:0x%x\n", ret);
        return;
    }

    task_2.pfnTaskEntry = (TSK_ENTRY_FUNC)device_read_thraed;
    task_2.uwStackSize = 2048;
    task_2.pcName = "device read thraed";
    task_2.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_2, &task_2);
    if (ret != LOS_OK)
    {
        printf("Falied to create task ret:0x%x\n", ret);
        return;
    }

    task_3.pfnTaskEntry = (TSK_ENTRY_FUNC)keypad_process;
    task_3.uwStackSize = 2048;
    task_3.pcName = "keypad_process";
    task_3.usTaskPrio = 20;
    ret = LOS_TaskCreate(&thread_id_3, &task_3);
    if (ret != LOS_OK)
    {
        printf("Falied to create keypad_process ret:0x%x\n", ret);
        return;
    }

    task_4.pfnTaskEntry = (TSK_ENTRY_FUNC)wifi_process;
    task_4.uwStackSize = 10240;
    task_4.pcName = "wifi_process";
    task_4.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_4, &task_4);
    if (ret != LOS_OK)
    {
        printf("Falied to create wifi_process ret:0x%x\n", ret);
        return;
    }
}

APP_FEATURE_INIT(smart_house_entry);